---
description: Компонент, предназначенный для отображения части пользовательского интерфейса во всплывающем окне.
---

<Overview group="modals">

# Popover [tag:component]

Компонент, предназначенный для отображения части пользовательского интерфейса во всплывающем окне.

</Overview>

<Playground>
  ```jsx
  <Popover
    placement="bottom"
    role="tooltip"
    aria-describedby="tooltip-1"
    content={
      <Div>
        <Text>Привет</Text>
      </Div>
    }
    restoreFocus="anchor-element"
  >
    <Button id="tooltip-1" mode="outline">
      Нажми на меня
    </Button>
  </Popover>
  ```
</Playground>

## Функциональность

Компонент позволяет отобразить всплывающее окно, позиционированное рядом с якорным элементом.
В качестве якорного используется элемент, переданный в свойство `children`.

> Обратите внимание, что если вы используете в качестве якорного элемента пользовательский компонент, то
> он должен передавать либо свойство `getRootRef`, либо реализовывать [forwardRef](https://react.dev/reference/react/forwardRef)
> на корневой `DOM`-элемент.
> Также передавайте на корневой элемент все `DOM`-атрибуты и обработчики событий
> (в частности, `onMouseOver`, `onMouseLeave`, `onClick`, `onFocus`, `onBlur`).

## Механизм вызова всплывающего окна

Свойство `trigger` определяет способ взаимодействия, при котором всплывающее окно будет отображаться или скрываться.

### `"click"`

Показ/скрытие происходит при нажатии на якорный элемент;

<Playground>
  ```jsx
  <Popover
    placement="bottom"
    role="tooltip"
    aria-describedby="tooltip-1"
    content={
      <Div>
        <Text>Привет</Text>
      </Div>
    }
    restoreFocus="anchor-element"
  >
    <Button id="tooltip-1" mode="outline">
      Нажми на меня
    </Button>
  </Popover>
  ```
</Playground>

### `"hover"`

Показ происходит при наведении мыши на якорных элемент, скрытие - при отведении.

Используйте как единственный механизм активации только для декоративных элементов в сочетании с `aria-hidden` и `disableFocusTrap` (см. секцию [Доступность (a11y)](#a11y))

> ⚠️ Предупреждение про `"hover"`:
>
> - Избегайте использования только `trigger="hover"`, так как пользователи клавиатуры или скринридеров не смогут использовать компонент.
> - На сенсорных экранах (тач-устройствах) будет работать как `"click"`, с единственным отличием, что всплывающее окно
>   не будет закрываться при повторном нажатии на целевой элемент. Для закрытия необходимо нажать
>   на область вне целевого элемента и всплывающего окна.

<Playground>
  ```jsx
  <Popover
    trigger="hover"
    placement="bottom"
    content={
      <Div>
        <Text>Привет</Text>
      </Div>
    }
    aria-hidden="true"
    disableFocusTrap
  >
    <Button mode="outline">Наведи на меня</Button>
  </Popover>
  ```
</Playground>

### `"focus"`

Показ происходит при фокусе на якорном элементе, скрытие - при потере фокуса;

<Playground>
  ```jsx
  <Popover
    trigger="focus"
    placement="bottom"
    role="tooltip"
    aria-describedby="tooltip-1"
    content={
      <Div>
        <Text>Привет</Text>
      </Div>
    }
    restoreFocus="anchor-element"
  >
    <Button id="tooltip-1" mode="outline">
      Сфокусируйся на меня (Tab или клик)
    </Button>
  </Popover>
  ```
</Playground>

### `"manual"`

Показ/скрытие контролируется только через свойство `shown`.
Обработчик, переданный в свойство `onShownChange`, будет вызываться при нажатии за пределами якорного и всплывающего элементов,
а также по кнопке `ESC`.

<Playground>

```jsx
const [shown, setShown] = React.useState(false);

const handleShownChange = React.useCallback((value, reason) => {
  if (!value) {
    switch (reason) {
      case 'callback':
      case 'escape-key':
      case 'click-outside':
        setShown(false);
        break;
      default:
        break;
    }
  }
}, []);

return (
  <Popover
    trigger="manual"
    shown={shown}
    placement="bottom"
    role="tooltip"
    aria-describedby="tooltip-1"
    onShownChange={handleShownChange}
    content={
      <Div>
        <Text>Привет</Text>
      </Div>
    }
    restoreFocus="anchor-element"
  >
    <Button id="tooltip-1" onClick={() => setShown((prev) => !prev)} mode="outline">
      Нажми на меня
    </Button>
  </Popover>
);
```

</Playground>

## Хук usePopover [#use-popover]

Вы можете использовать хук `usePopover`, который позволяет устанавливать якорный элемент для `Popover`,
не прокидывая его в качестве `children`.

<Playground>

```jsx
const { anchorRef, anchorProps, popover } = usePopover({
  'trigger': 'click',
  'role': 'dialog',
  'id': 'menupopup',
  'aria-labelledby': 'menubutton',
  'content': ({ onClose }) => (
    <Div>
      <Text>Привет</Text>
    </Div>
  ),
});

return (
  <>
    {popover}
    <Button getRootRef={anchorRef} id="menubutton" aria-controls="menupopup" {...anchorProps}>
      Нажми на меня
    </Button>
  </>
);
```

</Playground>
## Доступность (a11y) [#a11y]

### Текстовые метки

Старайтесь сопровождать элемент текстовым описанием для корректной работы скринридеров. Для этого
необходимо вручную передавать некоторые параметры.

- у всплывающего элемента обязательно должен быть указан [`role`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles).
  Зачастую это либо [`"tooltip"`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/tooltip_role), либо [`"dialog"`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/dialog_role);
- у якорного элемента, в зависимости от `role` всплывающего элемента, должны быть заданы атрибуты
  `aria-*`. Какие именно можно ознакомиться в документации конкретного `role`.

> **Исключение:** `aria-expanded` компонент выставляет самостоятельно в зависимости от `role`,
> поэтому об этом атрибуте можно не беспокоиться.

### `trigger="hover"` [#a11y-hover]

Использования `trigger="hover"`, как единственного механизма активации, приводит к тому, что события наведения не генерируются при клавиатурной навигации или скринридером.

Если нужно, чтобы контент из `Popover` был доступен, комбинируйте `hover` с триггером `focus`.

```jsx
// ❌ WCAG
<Popover trigger="hover">{children}</Popover>

// ✅ WCAG
<Popover trigger={['hover', 'focus']}>{children}</Popover>
```

## Свойства и методы [#api]

<PropsTable name="Popover">

### Popover [#popover-api]

### usePopover [#use-popover-api]

</PropsTable>
